package com.innjia.base.zima.sdk;

import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSONObject;
import com.antgroup.zmxy.openplatform.api.ZhimaApiException;
import com.antgroup.zmxy.openplatform.api.response.ZhimaCustomerCertificationInitializeResponse;
import com.antgroup.zmxy.openplatform.api.response.ZhimaCustomerCertificationQueryResponse;
import com.antgroup.zmxy.openplatform.api.response.ZhimaCustomerContractInitializeResponse;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.innjia.base.common.ResultInfo;
import com.innjia.base.common.ZimaConfig;
import com.innjia.base.common.ZimaConfig.SignBizCodeEnum;
import com.innjia.base.common.ZimaConfig.SignPosKeywordEnum;
import com.innjia.base.zima.util.ZhimaContractUtil;

/**
 * 芝麻电子合约
 * 
 * @author fangcheng.huang
 *
 */
public class ZhimaContractSdk {

	private static Logger logger = Logger.getLogger(ZhimaContractSdk.class);
	
	/**
	 * 合约初始化，获取电子合约号contractNo
	 * @param contractName
	 * @param contractFile
	 * @return
	 * ResultInfo
	 */
	public ResultInfo signContractInit(String contractName, String contractFile) {
		ResultInfo res = new ResultInfo("0", "合约初始化成功");
		if(StringUtils.isEmpty(contractName) || StringUtils.isEmpty(contractFile)) {
			logger.info("合约初始化参数不正确！");
			res.setCode("1");
			res.setMsg("合约初始化参数不正确！");
			return res;
		}
		//1、签约初始化
		Map<String, String> contractInitParams = new HashMap<String, String>();
		contractInitParams.put("contractName", contractName);
		contractInitParams.put("contractFile", contractFile);//base64文件流，大小不得超过5M
		this.transferZimaConfigToMap(contractInitParams);
		logger.info("=========可信签约初始化开始...");
		String contractNo = null;
		try {
			ZhimaCustomerContractInitializeResponse response = ZhimaContractUtil.contractInit(contractInitParams);
			if(response != null) {
				if(response.isSuccess()) {
					contractNo = response.getContractNo();
					res.setData(contractNo);
				} else {
					logger.info("========可信电子合约初始化失败，响应信息：" + JSONObject.toJSONString(response));
					res.setCode("1");
					res.setMsg(response.getErrorMessage());
				}
			} else {
				logger.info("========调用可信签约初始化接口无响应结果...");
				res.setCode("1");
				res.setMsg("合约初始化接口无结果");
			}
		} catch (ZhimaApiException e) {
			res.setCode("1");
			res.setMsg("合约初始化异常");
			logger.error("=========合约初始化异常！", e);
		}
		logger.info("可信签约初始化结束!contractNo:" + contractNo);
		return res;
	}
	
	/**
	 * 芝麻认证初始化，获取芝麻认证唯一标识bizNo
	 * @param params
	 * @return
	 * ResultInfo
	 */
	public ResultInfo signCertificationInit(Map<String, String> params) {
		ResultInfo res = new ResultInfo("0", "芝麻认证初始化成功");
		if(params == null) {
			logger.info("芝麻认证初始化参数错误,params=" + params);
			res.setCode("1");
			res.setMsg("芝麻认证初始化参数错误");
			return res;
		}
		String orderId = params.get("orderId");
		String certNo = params.get("certNo");
		String certName = params.get("certName");
		String bizCode = params.get("bizCode");
		if(StringUtils.isEmpty(orderId) || StringUtils.isEmpty(certNo) ||
				StringUtils.isEmpty(certName) || StringUtils.isEmpty(bizCode)) {
			logger.info("============芝麻认证初始化参数不正确！bizCode：" + bizCode);
			res.setCode("1");
			res.setMsg("芝麻认证初始化失败，参数不正确！认证类型:bizCode=" + bizCode);
			return res;
		}
		Map<String, String> certificationInitMap = new HashMap<String, String>();
		certificationInitMap.put("orderId", orderId);
		certificationInitMap.put("certName", certName);
		certificationInitMap.put("certNo", certNo);
		certificationInitMap.put("bizCode", bizCode);
		//手签必要参数
		if(SignBizCodeEnum.E_SIGN.name().equals(bizCode)) {
			String contractNo = params.get("contractNo");
			String signKeyword = params.get("signKeyword");
			if(StringUtils.isEmpty(contractNo) || StringUtils.isEmpty(signKeyword)) {
				logger.info("============芝麻认证初始化参数不正确！bizCode：" + bizCode);
				res.setCode("1");
				res.setMsg("芝麻认证初始化失败，参数不正确！认证类型:bizCode=" + bizCode);
				return res;
			}
			certificationInitMap.put("contractNo", contractNo);
			certificationInitMap.put("signPosKeyword", SignPosKeywordEnum.getkeyWordByName(signKeyword));
		}
		this.transferZimaConfigToMap(certificationInitMap);
		logger.info("芝麻认证初始化开始...");
		String bizNo = null;
		try {
			ZhimaCustomerCertificationInitializeResponse response = ZhimaContractUtil.certificationInit(certificationInitMap);
			if(response != null) {
				if(response.isSuccess()) {
					bizNo = response.getBizNo();
					res.setData(bizNo);
				} else {
					logger.info("==========芝麻认证初始化失败，响应信息：" + JSONObject.toJSONString(response));
					res.setCode("1");
					res.setMsg(response.getErrorMessage());
				}
			} else {
				logger.info("==========调用芝麻认证初始化接口无响应结果...");
				res.setCode("1");
				res.setMsg("============芝麻认证初始化接口无结果");
			}
		} catch (ZhimaApiException e) {
			res.setCode("1");
			res.setMsg("芝麻认证初始异常");
			logger.error("=========芝麻认证初始异常！", e);
		}
		logger.info("============芝麻认证初始化结束!bizNo:" + bizNo);
		return res;
	}
	
	/**
	 *  获取签名URL，H5方式跳转至该URL，自动唤起认证引导页；认证完成后跳转至商户回调URL并带回签名结果,需对该回调URL解析展示认证结果
	 * @param bizNo
	 * @param isHand true：核身手签，false：只核身
	 * @param signKeyword 用来区分甲乙方
	 * @return
	 * ResultInfo
	 */
	public ResultInfo signCertificationCertify(String bizNo, boolean isHand, String signKeyword) {
		ResultInfo res = new ResultInfo("0", "获取认证地址成功");
		if(StringUtils.isEmpty(bizNo)) {
			logger.info("开始认证参数错误！");
			res.setCode("1");
			res.setMsg("获取认证签名URL失败，参数不正确");
			return res;
		}
		Map<String, String> certificationCertifyMap = new HashMap<String, String>();
		certificationCertifyMap.put("bizNo", bizNo);
		if(isHand) {
			if(SignPosKeywordEnum.PARTY_A.name().equals(signKeyword)) {//甲方签约回调地址
				certificationCertifyMap.put("returnUrl", ZimaConfig.returnUrlLandlord);
			} else {//乙方签约回调地址
				certificationCertifyMap.put("returnUrl", ZimaConfig.returnUrlRenter);
			}
		}
		this.transferZimaConfigToMap(certificationCertifyMap);
		logger.info("=========芝麻开始认证接口获取认证URL调用开始...");
		String signUrl = null;
		try {
			signUrl = ZhimaContractUtil.certificationCertify(certificationCertifyMap);
			if(StringUtils.isEmpty(signUrl)) {
				res.setCode("1");
				res.setMsg("获取认证地址失败");
			} else {
				res.setData(signUrl);
			}
		} catch (ZhimaApiException e) {
			res.setCode("1");
			res.setMsg("获取认证地址发生异常");
			logger.error("======获取认证地址发生异常！", e);
		}
		logger.info("=====芝麻开始认证接口获取认证URL调用结束");
		return res;
	}
	
	/**
	 * 芝麻认证查询,获取签约认证合同信息
	 * @param bizNo
	 * @return
	 * ResultInfo
	 */
	public ResultInfo signCertificationQuery(String bizNo) {
		ResultInfo res = new ResultInfo("0", "查询成功");
		if(StringUtils.isEmpty(bizNo)) {
			logger.info("参数错误！bizNo:" + bizNo);
			res.setCode("1");
			res.setMsg("芝麻认证查询失败，参数错误");
			return res;
		}
		Map<String, String> certificationQueryMap = new HashMap<String, String>();
		certificationQueryMap.put("bizNo", bizNo);
		this.transferZimaConfigToMap(certificationQueryMap);
		try {
			ZhimaCustomerCertificationQueryResponse response = ZhimaContractUtil.certificationQuery(certificationQueryMap);
			if(response != null) {
				if(response.isSuccess() && "true".equals(response.getPassed().toLowerCase())) {
					List<Map> channelStatuses = new Gson().fromJson(response.getChannelStatuses(), new TypeToken<List<Map>>() {
					}.getType());
					Map<String, String> result = new HashMap<String, String>();
					String base64Contract = null;
					if(!channelStatuses.isEmpty()) {
						for(Map map : channelStatuses) {
							if(map.get("materials") != null) {
								result = (Map<String, String>)map.get("materials");
								base64Contract = result.get("CONTRACT");//CONTRACT,FACIAL_PICTURE_FRONT
							}
						}
						//合同信息
						res.setData(base64Contract);
					}
					res.setMsg("认证成功");
				} else {
					res.setCode("1");
					res.setMsg("认证失败：" + response.getFailedReason());
				}
			} else {
				res.setCode("1");
				res.setMsg("未查询到结果");
			}
		} catch (ZhimaApiException e) {
			res.setCode("0");
			res.setMsg("查询签约认证结果异常");
			logger.error("======查询签约认证结果异常！", e);
		}
		return res;
	}
	
	/**
	 * 解析签约回调，获取签约结果
	 * @param params
	 * @param sign
	 * @return
	 * String
	 */
	public String queryCertificationResult(String params, String sign) {
		if(StringUtils.isEmpty(params) || StringUtils.isEmpty(sign)) {
			logger.info("========签约回调参数错误");
			return null;
		}
		Map<String, String> map = new HashMap<String, String>();
		map.put("params", params);
		map.put("sign", sign);
		this.transferZimaConfigToMap(map);
		try {
			return ZhimaContractUtil.customerCertificationresult(map);
		} catch (UnsupportedEncodingException e) {
			logger.info("=======认证回调解析认证结果编码格式错误", e);
		} catch (ZhimaApiException e) {
			logger.error("=========认证回调解析认证结果异常", e); 
		}
		return null;
	}
	
	/**
	 * 只核身
	 * @param params key:orderId,certNo,certName
	 * @return
	 * ResultInfo
	 */
	public ResultInfo checkIdentity(Map<String, String> params) {
		ResultInfo res = new ResultInfo("1", "验证失败");
		if(params == null) {
			logger.info("只核身sdk参数错误,params=" + params);
			res.setMsg("只核身sdk参数错误");
			return res;
		}
		params.put("bizCode", SignBizCodeEnum.FACE.name());
		res = this.signCertificationInit(params);
		if("1".equals(res.getCode())) {
			res.setMsg("验证失败");
			return res;
		}
		String bizNo = (String)res.getData();
		return this.signCertificationCertify(bizNo, false, null);
	}
	
	private void transferZimaConfigToMap(Map<String, String> map) {
		if(map == null) {
			map = new HashMap<String, String>();
		}
		map.put("gatewayUrl", ZimaConfig.gatewayUrl);
		map.put("appId", ZimaConfig.appId);
		map.put("privateKey", ZimaConfig.privateKey);
		map.put("zimaPublicKey", ZimaConfig.zimaPublicKey);
		map.put("charset", ZimaConfig.charset);
	}
}
